#include <jni.h>
#include <string>
#include "YUVFaceJudge.h"
#include <android/log.h>
#include <opencv2/opencv.hpp>
#include <android/bitmap.h>


#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,"Terry",__VA_ARGS__)


jobject mat_to_bitmap(JNIEnv *env, cv::Mat &src, bool needPremultiplyAlpha, jobject bitmap_config) {
    jclass java_bitmap_class = (jclass) env->FindClass("android/graphics/Bitmap");
    jmethodID mid = env->GetStaticMethodID(java_bitmap_class,
                                           "createBitmap",
                                           "(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");

    jobject bitmap = env->CallStaticObjectMethod(java_bitmap_class,
                                                 mid, src.size().width, src.size().height,
                                                 bitmap_config);
    AndroidBitmapInfo info;
    void *pixels = 0;

    try {
        CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
        CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4);
        CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
        CV_Assert(pixels);
        if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
            cv::Mat tmp(info.height, info.width, CV_8UC4, pixels);
            if (src.type() == CV_8UC1) {
                cvtColor(src, tmp, CV_GRAY2RGBA);
            } else if (src.type() == CV_8UC3) {
                cvtColor(src, tmp, CV_RGB2RGBA);
            } else if (src.type() == CV_8UC4) {
                if (needPremultiplyAlpha) {
                    cvtColor(src, tmp, cv::COLOR_RGBA2mRGBA);
                } else {
                    src.copyTo(tmp);
                }
            }
        } else {
            // info.format == ANDROID_BITMAP_FORMAT_RGB_565
            cv::Mat tmp(info.height, info.width, CV_8UC2, pixels);
            if (src.type() == CV_8UC1) {
                cvtColor(src, tmp, CV_GRAY2BGR565);
            } else if (src.type() == CV_8UC3) {
                cvtColor(src, tmp, CV_RGB2BGR565);
            } else if (src.type() == CV_8UC4) {
                cvtColor(src, tmp, CV_RGBA2BGR565);
            }
        }
        AndroidBitmap_unlockPixels(env, bitmap);
        return bitmap;
    } catch (cv::Exception e) {
        AndroidBitmap_unlockPixels(env, bitmap);
        jclass je = env->FindClass("org/opencv/core/CvException");
        if (!je) je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, e.what());
        return bitmap;
    } catch (...) {
        AndroidBitmap_unlockPixels(env, bitmap);
        jclass je = env->FindClass("java/lang/Exception");
        env->ThrowNew(je, "Unknown exception in JNI code {nMatToBitmap}");
        return bitmap;
    }
}


extern "C"
JNIEXPORT jobject

JNICALL
Java_com_cloudream_algorithm_YUVImageTools_getYImage(
        JNIEnv *env,
        jobject obj,
        jstring jpath,
        jint width,
        jint height,
        jobject config) {

    YUVFaceJudgemine yuvFaceJudgemine;

    const char *chardata = (*env).GetStringUTFChars(jpath, 0);
    std::string path = chardata;


    std::vector<unsigned char> data = yuvFaceJudgemine.GetYImg(path, width, height);

    cv::Mat imageshow = cv::Mat::zeros(width, height, CV_8UC1);
    for (int row = 0; row < imageshow.rows; row++) {
        for (int col = 0; col < imageshow.cols; col++) {
            int i = row * height + col;
            imageshow.at<signed char>(row, col) = data.at(i);
        }
    }


    jobject _bitmap = mat_to_bitmap(env, imageshow, false, config);

    //get source bitmap's config
//    jclass java_bitmap_class = (jclass)env->FindClass("android/graphics/Bitmap");
//    jmethodID staticMethodId = env->GetStaticMethodID(java_bitmap_class,"createBitmap","(IILandroid/graphics/Bitmap$Config;)Landroid/graphics/Bitmap;");
//    jobject  _bitmap = env->CallStaticObjectMethod(java_bitmap_class,staticMethodId,1080,1920,config);



    return _bitmap;
}


extern "C"
JNIEXPORT jobject

JNICALL
Java_com_cloudream_algorithm_YUVImageTools_getBGRImage(
        JNIEnv *env,
        jobject obj,
        jstring jpath,
        jint width,
        jint height,
        jobject config) {

    YUVFaceJudgemine yuvFaceJudgemine;

    const char *chardata = (*env).GetStringUTFChars(jpath, 0);
    std::string path = chardata;


    std::vector<unsigned char> data = yuvFaceJudgemine.GetBGRImg(path, width, height);


    LOGI("BGRImage data.size = %ld", data.size());

    cv::Mat imageshow = cv::Mat::zeros(width, height, CV_8UC3);
    for (int row = 0; row < imageshow.rows; row++) {
        for (int col = 0; col < imageshow.cols; col++) {
            int i = row * height + col;
            imageshow.at<cv::Vec3b>(row, col)[0] = data.at(3 * i + 0);
            imageshow.at<cv::Vec3b>(row, col)[1] = data.at(3 * i + 1);
            imageshow.at<cv::Vec3b>(row, col)[2] = data.at(3 * i + 2);
        }
    }


    jobject _bitmap = mat_to_bitmap(env, imageshow, false, config);
    return _bitmap;
}

extern "C"
JNIEXPORT jobject

JNICALL
Java_com_cloudream_algorithm_YUVImageTools_getBGRAImage(
        JNIEnv *env,
        jobject obj,
        jstring jpath,
        jint width,
        jint height,
        jobject config) {

    YUVFaceJudgemine yuvFaceJudgemine;

    const char *chardata = (*env).GetStringUTFChars(jpath, 0);
    std::string path = chardata;


    std::vector<unsigned char> data = yuvFaceJudgemine.GetBGRImg(path, width, height);


    cv::Mat imageshow = cv::Mat::zeros(width, height, CV_8UC4);
    for (int row = 0; row < imageshow.rows; row++) {
        for (int col = 0; col < imageshow.cols; col++) {
            int i = row * height + col;
            imageshow.at<cv::Vec4b>(row, col)[0] = data.at(4 * i + 0);
            imageshow.at<cv::Vec4b>(row, col)[1] = data.at(4 * i + 1);
            imageshow.at<cv::Vec4b>(row, col)[2] = data.at(4 * i + 2);
            imageshow.at<cv::Vec4b>(row, col)[3] = data.at(4 * i + 3);
        }
    }

    jobject _bitmap = mat_to_bitmap(env, imageshow, false, config);

    return _bitmap;

}




